from tortoise import Tortoise
from tortoise.query_utils import Q

from app.lib.txt import path_str_arr
from app.model import mysql


async def new_menu(name, parent_id=0):
    """
    新增菜单
    :param name:
    :param parent_id:
    :return:
    """
    conn = Tortoise.get_connection("default")
    parent_path = ''
    level = 0
    if parent_id:
        parent_folder = await mysql.Menu.get_or_none(id=parent_id)
        if parent_folder:
            parent_path = parent_folder.path or ''
            level = parent_path.count('/')

    c = await conn.execute_query_dict(f'SELECT MAX(sort) as max_sort FROM {mysql.Menu.Meta.table} WHERE `parent_id`={parent_id}')
    max_sort = c[0].get('max_sort', 0) or 0

    menu = await mysql.Menu.create(
        name=name,
        parent_id=parent_id,
        parent_path=parent_path,
        level=level,
        sort=max_sort + 1,
    )
    menu.path = path_str_arr(parent_path, menu.id)
    await menu.save()
    return menu


async def nav_name(menu_id):
    """
    获取菜单列表
    :param menu_id:
    :return:
    """
    conn = Tortoise.get_connection("default")
    items = await conn.execute_query_dict(f'SELECT id, name, level, path, parent_path FROM {mysql.Menu.Meta.table} '
                                          f'WHERE parent_id={menu_id} ORDER BY sort ASC ')
    level_set = set([])
    level_dict = {}
    for item in items:
        nid = item.get('id', 0)
        level = item.get('level', 0)
        level_set.add(level)
        # 获取层级的路径列表
        level_ids = level_dict.get(level, [])
        level_ids.append(nid)
        level_dict[level] = level_ids
    levels = list(level_set)
    levels.sort()
    if len(levels) == 0:
        return []

    nodes = list()

    class Node(object):
        def __init__(self, nid: int, name: str, path: str, parent_path: str, children: list):
            """
            初始化
            :param name:
            :param desc:
            :param parent:
            :param children:
            """
            self.id = nid
            self.name = name
            self.path = path
            self.parent_path = parent_path
            self.children = children

        def get_nodes(self):
            """
            获取该节点下的全部结构字典
            """
            d = dict()
            d['id'] = self.id
            d['name'] = self.name
            # d['path'] = self.path
            # d['parent_path'] = self.parent_path
            children = self.get_children()
            if children:
                d['list'] = [child.get_nodes() for child in children]
            return d

        def get_children(self):
            """
            获取该节点下的全部节点对象
            """
            return [n for n in nodes if n.parent_path == self.path]

        def __repr__(self):
            return self.path

    # 将原始数据转换为节点对象
    for data in items:
        node = Node(data.get('id'), data.get('name', ''), data.get('path', ''), data.get('parent_path', ''), [])
        nodes.append(node)

    # 为各个节点建立联系
    for node in nodes:
        children_ids = [data.get('id') for data in items if data.get('parent_path') == node.path]
        children = [node for node in nodes if node.id in children_ids]
        node.children.extend(children)

    # 获取根阶段
    root_node_ids = level_dict.get(levels[0], [])
    root_nodes = [node for node in nodes if node.id in root_node_ids]
    nest_items = []
    for root_node in root_nodes:
        tree = root_node.get_nodes()
        nest_items.append(tree)

    return nest_items


async def get_menu(menu_id):
    """
    获取菜单
    :param menu_id:
    :return:
    """
    return await mysql.Menu.get_or_none(id=menu_id)


async def get_menu_names(menu_ids: list):
    """
    获取菜单名称列表
    :param menu_ids:
    :return:
    """
    names = await mysql.Menu.filter(Q(id__in=menu_ids)).values_list('name', flat=True) if menu_ids else []
    return names
